Add record/split_pair and record/disjoint_merge #1982
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is preliminary work for the rewriting of native contracts using the new immediate/delayed representation introduced in #1975, although this PR is fairly well-separated (and this is why this is a small separate PR).
In order to efficiently implement the contracts for static record types, which needs to know which fields to lock in the sealed tail, we need a way to split and recombine records which is efficient and preserves field metadata. The current implementation can do without because the immediate part and the delayed part are crammed into one function, and the current implementation is also probably quite inefficient (computing 2 record-as-sets differences in pure Nickel).
This PR adds two primops:
record/split_pair
corresponds exactly to what the Rust codeeval::merge::split::split
is doing: separate a pair of records into 4 parts, the fields that are in one of the operands but not the other, plus the fields that are common (but which is split in two because we have to choose if we take the value and field metadata's from the left operand or from the right operand).record/disjoint_merge
is a fast merge operation when both operands are known to be disjoints. It's closer to a union than a merge, although both coincide on such a special case, in that it doesn't interact with metadata or recursive definitions (although it does preserve metadata). This operation just puts everything in one record.Those primops might be also useful to efficiently implement other operations (record differences, record projection, etc.) in the stdlibin the future.